/******************************************************************************
 * SVN­Versioning-Information:
 * ­­­­­­­­­­­­­­­­­­­­­­­­---------------------
 * $LastChangedRevision: 6 $
 * $LastChangedBy: c.a.duevel $
 * $LastChangedDate: 2009-08-26 15:12:37 +0000 (Wed, 26 Aug 2009) $
 * $HeadURL: http://robofight.googlecode.com/svn/trunk/Server/src/de/hft_stuttgart/botwar/server/model/Coinsystem.java $
 ******************************************************************************/
package de.hft_stuttgart.botwar.server.model;

/**
 *
 * @author pmv-mail@gmx.de
 */
public final class Coinsystem {

    private static final long[] LEVEL_COINS = {
        0, // Level 1
        500, // Level 2
        1250, // Level 3
        2500, // Level 4
        5000, // Level 5
        7500 // Level 6
    };

    //for every possible playernumber, there is an array with
    //the result coins a player will get for his place
    private static final int[][] COIN_WIN = {
        {100, 50},
        {150, 75, 30},
        {180, 90, 45, 20}
    };

    //if a game with 2 players ends with draw, this amount of coins will be used
    private static final int COIN_DRAW = 25;

    //instanz of this class isn't allowed
    private Coinsystem() {
    }

    /**
     * Returns the number of coints a player gets for his gameresult.
     * @param playerNumber number of players in the game
     * @param place the own result place after the game
     * @return coins the player get
     * @throws java.lang.IllegalArgumentException to be thrown if the place is
     * higher than the playerNumber
     */
    public static long getCoinsForGame(final int playerNumber, final int place)
            throws IllegalArgumentException {
        if (playerNumber < 2) {
            throw new IllegalArgumentException(
                    "A game can't have less then 2 players!");
        }

        if (place <= 0) {
            throw new IllegalArgumentException(
                    "A final gameplace can't be zero or negativ!");
        }

        if (playerNumber > COIN_WIN.length + 1) {
            throw new UnsupportedOperationException(String.format(
                    "Playernumber %d is higher then %d!",
                    playerNumber, COIN_WIN.length + 1));
        }

        if (place > COIN_WIN[playerNumber - 2].length) {
            throw new IllegalArgumentException(String.format(
                    "Place %d out of playernumber %d!",
                    place, COIN_WIN[playerNumber - 2].length));
        }

        return COIN_WIN[playerNumber - 2][place - 1];
    }

    /**
     * Returns the number of coints a player gets for his gameresult.
     * If the player has a equal result as another player in the same game,
     * he will get other gamepoints for his place.
     * @param playerNumber number of players in the game
     * @param place the own result rank after the game
     * @param draw two or more players have the same gameresult = true
     * @return coins the player get
     * @throws java.lang.IllegalArgumentException to be thrown if the place is
     * higher than the playerNumber
     */
    public static long getCoinsForGame(final int playerNumber,
            final int place,
            final boolean draw)
            throws IllegalArgumentException {
        if (!draw) {
            return getCoinsForGame(playerNumber, place);
        }

        if (playerNumber != 2) {
            throw new UnsupportedOperationException(String.format(
                    "Draw for %d players not supported!", playerNumber));
        }

        return COIN_DRAW;
    }

    /**
     * Returns the level for the player with the given coinnumber
     * @param coins the amount of coins the player has
     * @return level of player
     */
    public static int getLevelForCoins(final long coins) {
        if (coins < 0) {
            throw new IllegalArgumentException("Coins can't be negativ!");
        }
        for (int i = 1; i < LEVEL_COINS.length; i++) {
            if (coins < LEVEL_COINS[i]) {
                return i;
            }
        }
        return LEVEL_COINS.length;
    }

    /**
     * Returns the allowed coins for a level
     * @param level level
     * @return allowed coins for the level
     */
    public static long getCoinsForLevel(final int level) {
        if (level <= 0) {
            throw new IllegalArgumentException(
                    "Level can't be negativ or zero!");
        }
        if (level > LEVEL_COINS.length) {
            return Long.MAX_VALUE;
        }
        return LEVEL_COINS[level - 1];
    }

    /**
     * Returns the highest possible rank
     * @return highest possible rank, the top level
     */
    public static int getTopLevel() {
        return LEVEL_COINS.length;
    }
}
